package appTool

import (
	"bufio"
	"fmt"
	"github.com/smallnest/rpcx/client"
	"github.com/smallnest/rpcx/protocol"
	"github.com/spf13/cobra"
	"log"
	"os"
	"sort"
	"strconv"
	"strings"
)

var rpcAddress string
var rpcDiscovery client.ServiceDiscovery
var xClientMap = map[string]client.XClient{}
var doFunc ServiceDoFunc

type ServiceDoFunc func(xclient client.XClient, fun string)
type GetServiceFun func() map[string]ServiceDoFunc

var sevIndex []string
var sevFuns = map[string]ServiceDoFunc{}

// 初始化debugTool
func InitDebugTool(app string, sevFun GetServiceFun) {
	cmd := &cobra.Command{
		Use:   "debug",
		Short: app + "调试工具",
		Long:  app + `调试工具`,
		Run:   cmdRun,
	}
	cmd.Flags().StringVar(&rpcAddress, "server", "", "rpcx地址")
	if sevFun != nil {
		for k, v := range sevFun() {
			sevIndex = append(sevIndex, k)
			sevFuns[k] = v
		}
		sort.Strings(sevIndex)
	}
	err := cmd.Execute()
	if err != nil {
		log.Fatal(err.Error())
	}
}

func cmdRun(cmd *cobra.Command, args []string) {
	rpcAddress = strings.TrimSpace(rpcAddress)
	if rpcAddress == "" {
		log.Fatal("rpcx地址不能为空")
	}
	fmt.Println("rpcx地址: ", rpcAddress)
	rpcDiscovery, _ = client.NewPeer2PeerDiscovery(rpcAddress, "")
	//err.MsgPackRegister(0)
	fmt.Println("rpc初始化完成")
	for {
		initService()
	}
}

func initService() {
	if sevFuns == nil || len(sevIndex) < 1 {
		log.Println("没有可服务对象")
		return
	}
	var servicePath string
	if len(sevIndex) == 1 {
		servicePath = sevIndex[0]
		doFunc = sevFuns[servicePath]
	} else {
		for {
			fmt.Println("============================")
			fmt.Println("选择调用对象")
			for k, v := range sevIndex {
				fmt.Printf(" %d. %s\n", k, v)
			}
			fun := DebugToolInput("")
			if fun == "exit" {
				log.Println("退出")
				os.Exit(0)
			}
			funNum, err := strconv.ParseInt(fun, 10, 64)
			if err != nil || funNum >= int64(len(sevIndex)) || funNum < 0 {
				log.Println("输入错误")
				continue
			}
			servicePath = sevIndex[funNum]
			doFunc = sevFuns[servicePath]
			break
		}
	}
	xclient := xClientMap[servicePath]
	option := client.DefaultOption
	option.SerializeType = protocol.JSON
	if xclient == nil {
		xclient = client.NewXClient(servicePath, client.Failover,
			client.RoundRobin, rpcDiscovery, option)
		xClientMap[servicePath] = xclient
	}
	fun := DebugToolInput("函数名: ")
	if fun == "exit" {
		log.Println("退出")
		os.Exit(0)
	}
	doFunc(xclient, fun)
}

func DebugToolInput(prefix string) string {
	if prefix == "" {
		prefix = "> "
	}
	for {
		fmt.Print(prefix)
		stdin := bufio.NewScanner(os.Stdin)
		if stdin.Scan() {
			str := stdin.Text()
			if str != "" {
				return str
			}
		}
		log.Println("输入失败,请重新输入")
	}
}
